昨天最後停在 ai_network_entry_t
這個結構體,然後透過 static const
去定義了這個 network 的資料:
static const ai_network_entry_t networks[AI_MNETWORK_NUMBER] = {
{
.name = (const char *)AI_NETWORK_MODEL_NAME,
.config = AI_NETWORK_DATA_CONFIG,
.ai_get_report = ai_network_get_report,
.ai_create = ai_network_create,
.ai_destroy = ai_network_destroy,
.ai_get_error = ai_network_get_error,
.ai_init = ai_network_init,
.ai_run = ai_network_run,
.ai_forward = ai_network_forward,
.ai_data_params_get = ai_network_data_params_get,
.activations = data_activations0
},
};
今天要參考這個結構體裡面定義的內容繼續解析究竟是如何初始化整個模型的。
昨天有說到會先透過ai_network_find
來確定是否存在 network,若存在則回傳 nn_name 並且進入 aiBoostrap
,接著所有的初始化就會在 aiBootstrap
中完成。
最一開始會先進入一系列的檢查以後,最後會呼叫上面定義的結構體中的 .ai_create
作為 create 的方法,而這個方法會存在於 network.c 中,也就是透過 ST 轉檔案後產出的 network C code,而這個檔案會後會呼叫 Middleware/ST/AI 底下的 ai_platform_network_create
來進行 network 的建立。
而下一個則會呼叫 ai_mnetwork_get_report
來取得已建立的 network 資訊,而這個也會對應到上面結構體的 .ai_get_report
並且最後對應到 ST 的 API 取得資訊。
這邊的 get report 應該主要是用來檢查 model 的建立是否成功。
下一個則是進行 ai_mnetwork_init
,如下:
AI_API_ENTRY
ai_bool ai_mnetwork_init(ai_handle network)
{
struct network_instance *inn;
ai_network_params par;
inn = ai_mnetwork_handle((struct network_instance *)network);
if (inn) {
inn->entry->ai_data_params_get(&par);
for (int idx=0; idx < par.map_activations.size; idx++)
AI_BUFFER_ARRAY_ITEM_SET_ADDRESS(&par.map_activations, idx, inn->entry->activations[idx]);
return inn->entry->ai_init(inn->handle, &par);
}
else
return false;
}
可以看到他呼叫了 ai_data_params_get
這個 function,這個 function 對應到的是在 network_data.c 底下的 ai_bool ai_network_data_params_get(ai_network_params* params)
/*!
* @brief Get network params configuration data structure.
* @ingroup network_data
* @return true if a valid configuration is present, false otherwise
*/
AI_API_ENTRY
ai_bool ai_network_data_params_get(ai_network_params* params)
{
if (!params) return false;
const ai_buffer_array map_activations =
AI_BUFFER_ARRAY_OBJ_INIT(AI_FLAG_NONE, AI_NETWORK_DATA_ACTIVATIONS_COUNT, g_network_data_map_activations);
const ai_buffer_array map_weights =
AI_BUFFER_ARRAY_OBJ_INIT(AI_FLAG_NONE, AI_NETWORK_DATA_WEIGHTS_COUNT, g_network_data_map_weights);
return ai_platform_bind_network_params(params, &map_weights, &map_activations);
}
可以看到一個 network 的 activations 和 weights 資料就是在這邊被讀取的。
然後在 ai_network_init
(network.c 底下)中再透過讀取到的參數初始化整張網絡:
AI_API_ENTRY
ai_bool ai_network_init(
ai_handle network, const ai_network_params* params)
{
ai_network* net_ctx = AI_NETWORK_OBJ(ai_platform_network_init(network, params));
ai_bool ok = true;
if (!net_ctx) return false;
ok &= network_configure_weights(net_ctx, params); // <--- 這邊
ok &= network_configure_activations(net_ctx, params); // <--- 這邊
ok &= ai_platform_network_post_init(network);
return ok;
}
而在最後再 get report 以後使用 aiPrintNetworkInfo
輸出 network 資訊。
上面一通分析可能可能已經暈頭轉向了,但是為了之後要自己使用 network 的函式庫,還是得先看懂實際上是怎麼呼叫這些內容的,底下是簡略的 call-graph 來表示整個 AI Init 的過程:
於是我們可以總結,如果需要進行一個 network 的建立,最少需要依序 call 底下幾個 function :
ai_network_create
<-- 建立 network contextai_network_data_params_get
<-- 取得 activations 和 weightsai_network_init
<-- 傳入 activations 和 weights 後初始化模型這幾個就是透過 ST 轉換 model 所產生的 network C code 息息相關的幾個方法,呼叫完以後就能夠順利把整個模型建立起來了。
今天就先分享到這邊,明天開始分析 inference 相關的程式~